package com.logic.landseaserver.service.impl;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.common.util.QueryUtil;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.domain.Check;
import com.logic.landseaserver.domain.Procedure;
import com.logic.landseaserver.persistence.read.ProcedureReadMapper;
import com.logic.landseaserver.persistence.write.ProcedureWriteMapper;
import com.logic.landseaserver.service.ICheckService;
import com.logic.landseaserver.service.IProcedureService;
import com.logic.landseaserver.ws.dto.ProcedureDTO;

@Service
public class ProcedureServiceImpl implements IProcedureService {

	@Autowired
	private ProcedureReadMapper procedureReadMapper;

	@Autowired
	private ProcedureWriteMapper procedureWriteMapper;

	@Autowired
	private ICheckService checkServiceImpl;

	@Override
	public void delete(String arg0) throws BusinessException {
	    String[] idArr = arg0.split(",");
	    for (String id : idArr) {
	      Integer procedureId = Integer.valueOf(id);
	      Procedure procedure = (Procedure) this.get(procedureId);
	      Boolean pass = this.validateForDelete(procedure);
	      if (pass) {
	    	  procedure.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
	    	  procedureWriteMapper.deleteByPrimaryKey(procedure);
	      }
	    }

	}

	@Override
	public Object get(Integer arg0) throws BusinessException {
		return procedureReadMapper.selectByPrimaryKey(arg0);
	}

	@Override
	public int insert(Object arg0) throws BusinessException {
		Integer id = -1;
		Boolean pass = this.validateForInsert(arg0);
		if (pass) {
			Procedure procedure = (Procedure) arg0;
			procedure.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
			procedureWriteMapper.insertSelective(procedure);
			id = procedure.getId();
		}
		return id;
	}

	@Override
	public List<?> query(QueryUtil arg0) {
		return procedureReadMapper.getProcedureList(arg0);
	}

	@Override
	public void update(Object arg0) throws BusinessException {
		Boolean pass = this.validateForUpdate(arg0);
		if (pass) {
			Procedure procedure = (Procedure) arg0;
			procedure.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
			procedure.setCreatedBy(null);
			procedure.setCreatedDtm(null);
			procedureWriteMapper.updateByPrimaryKeySelective(procedure);
		}

	}

	@Override
	public Boolean validate(Object arg0) throws BusinessException {
		Boolean pass = true;
		if (arg0 == null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_Insert_Or_Update_Empty_Object);
		}
		if (!(arg0 instanceof Procedure)) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_Insert_Or_Update_Type);
		}
		Procedure procedure = (Procedure) arg0;
		if (procedure.getTemplate() != null && procedure.getTemplate()) {
			Procedure nameProcedure = procedureReadMapper.selectByName(procedure.getName());
			if (nameProcedure != null && !nameProcedure.getId().equals(procedure.getId())) {
				throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_Insert_Or_Update_Name_Repeat);
			}
		}
		return pass;
	}

	@Override
	public Boolean validateForDelete(Object arg0) throws BusinessException {
		return true;
	}

	@Override
	public Boolean validateForInsert(Object arg0) throws BusinessException {
		Boolean pass = false;
		pass = this.validate(arg0);
		Procedure procedure = (Procedure)arg0;
		if (procedure.getId() != null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_ID);
		}
		if (StringUtils.isBlank(procedure.getName())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_Procedure_Name);
		}
		if (StringUtils.isBlank(procedure.getSerialNum())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_Procedure_Number);
		}
		if (StringUtils.isBlank(procedure.getType())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_Procedure_Type);
		}
		if (procedure.getDuration() == null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_Procedure_Duration);
		}
		if (StringUtils.isBlank(procedure.getDescription())) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_CreateProcedure_Empty_Procedure_Description);
		}
		return pass;
	}

	@Override
	public Boolean validateForUpdate(Object arg0) throws BusinessException {
		Boolean pass = false;
		pass = this.validate(arg0);
		Procedure procedure = (Procedure)arg0;
		if (procedure.getId() == null) {
			throw new LandseaBusinessException(LandseaErrorMessageEnum.Procedure_UpdateProcedure_Empty_Procedure_ID);
		}
		return pass;
	}


	@Override
	public List<ProcedureDTO> queryDTO(QueryUtil queryUtil) {
		return procedureReadMapper.getProcedureDTOList(queryUtil);
	}

	@Override
	public ProcedureDTO getDTO(Integer procedureId) {
		return procedureReadMapper.selectDTOByPrimaryKey(procedureId);
	}

	@Override
	public void add2Template(Procedure procedure) throws BusinessException {
		//add to template
		procedure.setId(null);
		this.insert(procedure);

	}

	@Override
	public Procedure copyFromTemplate(Integer procedureId) throws BusinessException {
		Procedure template = (Procedure) this.get(procedureId);
		Procedure procedure = this.buildProcedure(template);
		this.insert(procedure);
		return procedure;
	}

	//prepare for copy procedure from template
	private Procedure buildProcedure(Procedure template) throws BusinessException {
		Procedure procedure = new Procedure();
		procedure.setActualEndDtm(template.getActualEndDtm());
		procedure.setActualStartDtm(template.getActualStartDtm());
		procedure.setDescription(template.getDescription());
		procedure.setDuration(template.getDuration());
		procedure.setEndCheckId(template.getEndCheckId());// new end check
		procedure.setEstimateEndDtm(template.getEstimateEndDtm());
		procedure.setEstimateStartDtm(template.getEstimateStartDtm());
		procedure.setName(template.getName());
		procedure.setPreProcedureId(template.getPreProcedureId());// new previous procedure
		procedure.setSerialNum(template.getSerialNum());
		procedure.setStartCheckId(template.getStartCheckId());// new start check
		procedure.setStatus(template.getStatus());
		procedure.setType(template.getType());
		procedure.setTemplate(false);
		Integer preProcedureId = procedure.getPreProcedureId();
		Integer startCheckId = procedure.getStartCheckId();
		Integer endCheckId = procedure.getEndCheckId();
		if (preProcedureId != null && preProcedureId != -1) {
			Procedure newProcedure1 = this.copyFromTemplate(preProcedureId);
			procedure.setPreProcedureId(newProcedure1.getId());
		}
		if (startCheckId != null && startCheckId != -1) {
			Check startCheck = checkServiceImpl.copyFromTemplate(startCheckId);
			procedure.setStartCheckId(startCheck.getId());
		}
		if (endCheckId != null && endCheckId != -1) {
			Check endCheck = checkServiceImpl.copyFromTemplate(endCheckId);
			procedure.setEndCheckId(endCheck.getId());
		}
		return procedure;
	}


	@Override
	public Check addCheck(Integer procedureId, Integer checkId) throws BusinessException {
		Check check = checkServiceImpl.copyFromTemplate(checkId);
		return check;
	}

	@Override
	public List<ProcedureDTO> queryByProjectId(QueryUtil queryUtil) {
		return procedureReadMapper.queryByProjectId(queryUtil);
	}

	@Override
	public Integer countByProjectId(Integer projectId) {
		return procedureReadMapper.countByProjectId(projectId);
	}

	@Override
	public Integer sumDurationByProjectId(Integer projectId) {
		return procedureReadMapper.sumDurationByProjectId(projectId);
	}

	@Override
	public List<Procedure> getByProjectId(Integer projectId) {
		return procedureReadMapper.getByProjectId(projectId);
	}

}
